<?php
namespace app\api\controller\v1;

use app\api\model\v1\Account as AccountModel;

/**
 * 我的账户
 * 访问：/api/v1.account/方法名；
 * 忘记密码：一般是给用户生成新密码。
 */
class Account extends Base
{
    // <1.0>
    // 短信验证码
    public function code()
    {
        try {
            // 在控制器内进行验证；
            $data = $this->jmParameter(['username', 'account_id', 'action']);
            
            $validateResult = $this->validate($data, [
                'username|用户名'  => ['require', 'regex'=>'/^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/'],
                'account_id|账户ID'  => ['regex'=>\jm\helper\Check::$regexpArray['id']],
                'action|动作类型'  => 'require|in:register,reset,login'
            ], $this->jmSetMessage([
                'username.regex' => '手机号码无效',
                'action.in' => '动作类型无效',
            ]));
            if (true !== $validateResult) {
                return $this->jmReturnJson(4001, $validateResult);
            }

            // 清除值为空的key；
            $this->jmUnsetEmpty($data);
            
            // 如果有 account_id，说明已有账户，此时是短信验证码登录或者重置密码；
            if (isset($data['account_id'])) {
                $accountModel = AccountModel::field(['id', 'password', 'code'])->find($data['account_id'] * 1);
            } else {
                // 根据手机号码查询记录；
                $accountModel = AccountModel::field(['id', 'password', 'code'])->where('username', $data['username'])->find();
            }

            if ($data['action'] === 'register' && !is_null($accountModel)) {
                return $this->jmReturnJson(4010, '账户已注册，请登录');
            }

            if ($data['action'] === 'login' || $data['action'] === 'reset') {
                // 测试时遇到了为空的情况，因为输入的手机号没有注册过，应该做个判断；
                if (is_null($accountModel)) {
                    return $this->jmReturnJson(4004, '此账号不存在');
                }
            }

            // 短信验证码；
            
            // 接口生成验证；
            $code = strval(mt_rand(100000, 999999));

            // http://www.smschinese.cn/api.shtml 发送短信接口；
            $sendUrl = "http://utf8.api.smschinese.cn/?Uid=mmdl1901&Key=d41d8cd98f00b204e980&smsMob={$data['username']}&smsText=验证码:{$code}";
            $smsResponseContent = \jm\helper\Request::smschinese($sendUrl);
            // \Dev::ve($smsResponseContent);// string(1) "1"
            if (($smsResponseContent * 1) >= 1) {                
                // if (is_null($accountModel)) {
                if ($data['action'] === 'register') {
                    // 新增记录；
                    $accountModel = new AccountModel();
                    $accountModel->username = $data['username'];
                    $accountModel->code = $code;
                    $isSuccess = $accountModel->isUpdate(false)->save();
                } else {
                    // 重置密码或者短信验证码登录；
                    $accountModel->code = $code;
                    $isSuccess = $accountModel->isUpdate(true)->save();
                }

                if ($isSuccess === 0) {
                    return $this->jmReturnJson(4002, '操作失败，请重试');
                }

                return $this->jmReturnJson(200, '发送短信验证码成功', [
                    'account_id' => $accountModel->id,
                    'code' => $code
                ]);
            }

            return $this->jmReturnJson(4003, '发送短信验证码失败');
        } catch (\Exception $e) {
            return $this->jmException($e);
        }
    }

    // <1.0>
    // 账号注册 / 手机号注册（无需发送短信）；
    // 以及忘记密码时的重置密码，此时action 值为 reset；
    public function register()
    {
        try {
            // 在控制器内进行验证
            $data = $this->jmParameter(['account_id', 'username', 'password', 'code', 'action']);
            
            $validateResult = $this->validate($data, $this->jmSetRule([
                'username|用户名'  => ['require', 'regex'=>'/^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/'],
                'password|密码' => 'require|min:6',
                'code|验证码' => 'require|number|length:6',
                'action|动作类型' => 'eq:reset'
            ]), ['username.regex' => '手机号码无效']);
            if (true !== $validateResult) {
                // 验证失败 输出错误信息（不管几个字段发生错误，这里只能得到第一个字段的错误信息：字符串。）
                return $this->jmReturnJson(4001, $validateResult);
            }

            $mcryptAES = new \jm\helper\McryptAES(\think\Config::get('password.mcrypt_key'));
            $data['password'] = $mcryptAES->decrypt($data['password']);

            // 查询是否占用
            $accountModel = AccountModel::field(['id', 'username', 'password', 'code'])->find($data['account_id']);
            // SELECT `id` FROM `yx_user` WHERE ( `username` = 'aa' ) AND `yx_user`.`deleted_at` IS NULL LIMIT 1
            
            // 为空说明还没有发送过验证码
            if (is_null($accountModel)) {
                return $this->jmReturnJson(4002, '请获取验证码');
            } else if ($accountModel->username !== $data['username']) {
                // 说明根据account_id找到的数据和当前用户不是同一个人；
                return $this->jmReturnJson(4003, '用户名有误');
            } else if (empty($data['action']) && $accountModel->password !== '') {
                // 说明注册过了
                return $this->jmReturnJson(4003, '账户已存在');
            }

            // 有记录，且密码为空，进行注册或者重置密码；

            // 验证码是否一致
            if ($accountModel->code != $data['code']) {
                return $this->jmReturnJson(4004, '验证码不正确');
            }

            // 密码加密并且保留原密码待以后方便处理，如果以后用不着的话则删除即可；
            $accountModel->code = 'ok';
            $accountModel->password2 = \jm\helper\Random::rand(3) . $data['password'] . \jm\helper\Random::rand(3);
            $accountModel->password = $this->_cryptPassword($data['password']);
            // $accountModel->jpush_id = $data['jpush_id'];
            $isSuccess = $accountModel->isUpdate(true)->save();
            if ($isSuccess === 0) {
                return $this->jmReturnJson(4005, '注册失败，请重试');
            }

            // 注册成功，同步注册云盘账户；重置密码时也需要重新注册一个云盘账号；
            $cloudResponse = \jm\helper\Request::post(\think\Config::get('clouddisk.domain') . 'api/register/register.php', 
                ['content-type' => 'x-www-form-urlencoded'], [
                    'username' => $data['username'],
                    'password' => $data['password']
            ]);
            // 结果是json字符串：string(68) "{"code":"0","message":"\u521b\u5efa\u6210\u529f","status":"success"}"。
            $res = json_decode($cloudResponse, true);
            // 创建云盘失败了要记录；
            if (($res['code'] * 1) !== 0) {
                \think\Db::name('clouddisk')->insert(array_merge([
                    'username' => $data['username'],
                    'password' => $data['password']
                ], $res));
            }

            return $this->jmReturnJson(200, empty($data['action']) ? '注册成功' : "密码重置成功", ['account_id'=>$accountModel->id]);
        } catch (\Exception $e) {
            return $this->jmException($e);
        }
    }

    // <1.0>
    // 账户登录
    // 账户登录（用户名和密码登录）；
    // 以及验证码登录，此时action 值为 code；
    public function login()
    {
        try {
            $data = $this->jmParameter(['username', 'password', 'jpush_id', 'code', 'action']);
            // 'jpush_id|极光注册ID' => 'require',// 需要用户同意的，所以是可选的；
            
            // 清除值为空的key
            $this->jmUnsetEmpty($data);

            $loginAction = isset($data['action']) ? $data['action'] : '' ;

            // 密码登录时才执行；
            if (!$loginAction || $loginAction == 'password') {
                $mcryptAES = new \jm\helper\McryptAES(\think\Config::get('password.mcrypt_key'));
                $data['password'] = $mcryptAES->decrypt($data['password']);
            }            

            $jpushId = '';
            if (isset($data['jpush_id'])) {
                $jpushId = $data['jpush_id'];
                unset($data['jpush_id']);
            }

            
            // 验证码登录
            if (isset($data['action']) && $loginAction == 'code') {
                $validateResult = $this->validate($data, 'Account.loginCodeRequired');
                if (true !== $validateResult) {
                    return $this->jmReturnJson(4001, $validateResult);
                }

                $errmsg = '用户名或验证码不正确';
            } else {
                // 用户名和密码登录
                $validateResult = $this->validate($data, 'Account.loginPasswordRequired');
                if (true !== $validateResult) {
                    return $this->jmReturnJson(4001, $validateResult);
                }

                // 密码加密
                $data['password'] = $this->_cryptPassword($data['password']);

                $errmsg = '用户名或密码不正确';
            }

            unset($data['action']);

            // 重复性校验
            $accountModel = AccountModel::field(['id', 'username', 'nickname', 'real_name', 'id_card', 'email', 'headimg', 'bank_card', 'gender', 'address', 'edu_bg_id', 'last_login_at', 'region_id', 'device_count', 'jpush_id', 'created_at'])->where($data)->find();
            if (is_null($accountModel)) {
                return $this->jmReturnJson(4002, $errmsg);
            }

            $integral = 0;
            // 动态计算积分
            $reward = $this->jmReward($accountModel['id']);
            if ($reward['errcode'] === 200) {
                $integral = $reward['data']['reward'];
            }

            // 登录成功，更新；
            $accountModel->last_login_at = \jm\helper\DateTime::YMDHISWithLine();
            $accountModel->jpush_id = $jpushId;
            if ($loginAction && $loginAction == 'code') {
                $accountModel->code = 'ok';
            }
            $accountModel->isUpdate(true)->save();// 也不是特别重要，所以不判断是否操作成功了；

            $retData = [
                'errcode' => 200,
                'message' => '登录成功',
                'data' => []
            ];

            // 返回一些信息
            if (!empty($accountModel['headimg'])) {
                $accountModel['headimg'] = $this->httpDomain . $accountModel['headimg'];
            }

            $retData['data']['info'] = array_merge(json_decode(json_encode($accountModel), true), ['integral' => $integral]);

            // 学历列表和地区列表必须同时返回，否则edu_bg_id 和region_id 返回的没有意义；
            
            $eduArray = $this->_edu();
            if ($eduArray['errcode'] === 0) {
                $retData['data']['edu'] = $eduArray['data'];
            } else {
                return ['errcode'=>0, 'message'=>'获取教育程度数据失败'];
            }

            $regionArray = $this->_region();
            if ($regionArray['errcode'] === 0) {
                $retData['data']['region'] = $regionArray['data'];
            } else {
                return ['errcode'=>0, 'message'=>'获取地区数据失败'];
            }

            // 文档类型
            $retData['data']['doc_type'] = ["agreement"=>0,"help"=>1,"about"=>2];

            // 意见反馈、故障报修
            $retData['data']['feedback_type'] = ["advice"=>1, "hitch"=>2];

            return json($retData);
        } catch (\Exception $e) {
            return $this->jmException($e);
        }
    }

    // 加密密码
    private function _cryptPassword($password)
    {
        return base64_encode($password);
    }

    // <1.0>
    // 账户信息 / 账户设置；
    public function setInfo()
    {
        try {
            $accountId = $this->jmParameter('account_id', 0);
            $validateResult = $this->jmValidateAccountId($accountId);
            if (true !== $validateResult) {
                return json($validateResult);
            }

            // headimg 取出来，便于在修改时删除旧图片；
            $accountModel = AccountModel::field(['id', 'headimg'])->find($accountId);
            if (is_null($accountModel)) {
                return $this->jmReturnJson(4001, '账户不存在');
            }

            $retSuccData = ['errcode'=>200, 'message'=>''];
            $retFailData = ['errcode'=>4002, 'message'=>''];
            $succflag = false;

            $type = $this->jmParameter('type');
            $result = ['message'=>'未知原因'];
            switch ($type) {
                // 仅头像
                case 'headimg':
                    $result = $this->_headimg($accountModel);
                    if ($result['errcode'] === 0) {
                        $retSuccData['data'] = ['url' => $result['url']];
                        $succflag = true;
                    }
                    break;
                default:
                    // 一次性设置多个信息；
                    $result = $this->_multi($accountModel);

                    // 没有头像，而且成功；
                    if ($result === true) {
                        $retSuccData['message'] = '信息设置成功';
                        $succflag = true;
                    } else if ($result['errcode'] === 200) {
                        // 有头像，而且成功；
                        $retSuccData['message'] = '信息设置成功';
                        $retSuccData['data'] = ['url' => $result['url']];
                        $succflag = true;
                    } else {
                        $retFailData['message'] = '信息设置失败：'. $result['message'];
                    }
                    break;
            }

            if ($succflag) {
                $retSuccData['message'] = empty($retSuccData['message']) ? '头像绑定成功' : $retSuccData['message'];
                return json($retSuccData);
            }

            $retFailData['message'] = empty($retFailData['message']) ? '头像绑定失败（'. $result['message'] .'）' : $retFailData['message'];
            return json($retFailData);
        } catch (\Exception $e) {
            return $this->jmException($e);
        }
    }

    // 单独设置头像（因为用过的App中，很多都是单独修改头像的）
    private function _headimg($accountModel)
    {
        try {
            $file = $this->request->file('headimg');
            if (is_null($file)) {
                return ['errcode'=>4001, 'message'=>'没有文件'];
            }

            $uploadResult = \jm\helper\File::save($file, $accountModel->headimg);
            if ($uploadResult['errcode'] === 200) {
                $accountModel->headimg = $uploadResult['data'];
                $accountModel->isUpdate(true)->save();
                return ['errcode'=>0, 'message'=>'上传成功', 'url'=>$this->httpDomain . $uploadResult['data']];
            }

            return ['errcode'=>4002, 'message'=>'上传失败'];
        } catch (\Exception $e) {
            return $this->jmException($e, false);
        }
    }

    // 一次设置多个信息
    private function _multi($accountModel)
    {
        try {
            $data = $this->jmParameter(['real_name','email','id_card','edu_bg_id','region_id','address','bank_card','gender']);

            $validateResult = $this->validate($data, [
                'real_name|真实姓名' => 'require|length:2,30',
                // 'mobile|手机号码' => ['require', 'number', 'regex'=>\jm\helper\Check::$regexpArray['mobile']],// 必须带有require，否则不传递该参数时不会进行验证；
                'email|电子邮箱' => 'require|email|length:3,100',
                // 'id_card|身份证号码' => 'require|length:15,18',
                'id_card|身份证号码' => ['require', 'regex'=>'/^[1-9][0-7]\d{4}((19\d{2}(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(19\d{2}(0[13578]|1[02])31)|(19\d{2}02(0[1-9]|1\d|2[0-8]))|(19([13579][26]|[2468][048]|0[48])0229))\d{3}(\d|X|x)?$/'],
                'edu_bg_id|教育程度ID' => 'require|number|egt:1',
                'region_id|地区ID' => 'require|number|egt:1',
                'address|联系地址' => 'require|length:2,255',
                'bank_card|银行卡号码' => 'require|number|length:10,32',
                'gender|性别' => 'number|in:0,1,2'
            ]);
            if (true !== $validateResult) {
                return ['errcode'=>4001, 'message'=>$validateResult];
            }

            // 1,
            // 假设性别非必须，那么可以不传递该参数，此时 $data['gender'] 的值是空字符串；
            // 操作数据库时，不应该把 gender 也带上，所以需要 unset()；
            // 2,
            // 把那些应该为 int 转为int，比如各种id；
            // 性别不能转为 int，因为表中的字段类型是 enum，其实就是字符串。
            $this->jmUnsetEmptyAndTrans2int($data, ['edu_bg_id','region_id']);
            \jm\helper\Db::setAttribute($accountModel, $data);

            // 头像和其他信息一起处理时
            $file = $this->request->file('headimg');
            
            // 没有头像
            if (is_null($file)) {
                $isSuccess = $accountModel->isUpdate(true)->save();
                if ($isSuccess) {
                    return true;
                } else {
                    return ['errcode'=>4002, 'message'=>'保存失败'];
                }
            }

            // 有头像
            // 若有旧图片则删除
            $uploadResult = \jm\helper\File::save($file, $accountModel->headimg);

            if ($uploadResult['errcode'] === 200) {
                $accountModel->headimg = $uploadResult['data'];
                $isSuccess = $accountModel->isUpdate(true)->save();
                if ($isSuccess) {
                    return ['errcode'=>200, 'message'=>'操作成功', 'url'=>$this->httpDomain . $uploadResult['data']];
                } else {
                    return ['errcode'=>4002, 'message'=>'保存失败'];
                }                
            } else {
                return ['errcode'=>4003, 'message'=>'头像上传失败'];
            }
        } catch (\Exception $e) {
            return $this->jmException($e, false);
        }
    }

    // 教育程度列表
    private function _edu()
    {
        try {
            $eduArray = \think\Db::query("SELECT id,title FROM ". $this->dbTablePrefix ."edu_bg WHERE deleted_at IS NULL");
            return [
                'errcode' => 0,
                'message' => '获取教育程度数据成功',
                'data' => $eduArray
            ];
        } catch (\Exception $e) {
            return $this->jmException($e, false);
        }
    }

    // 地区数据（仅有一级数据--省和直辖市）
    private function _region()
    {
        try {
            $regionArray = \think\Db::query("SELECT id,name FROM ". $this->dbTablePrefix ."region WHERE p_id=1");
            return [
                'errcode' => 0,
                'message' => '获取地区数据成功',
                'data' => $regionArray
            ];
        } catch (\Exception $e) {
            return $this->jmException($e, false);
        }
    }

    // 提供给 webdav 的接口：根据 imei/sn 获取用户的用户名和密码。
    // 假定，一个 imei/sn 对应一个用户。
    public function getUserForCloudDisk() {
        try {
            $data = $this->jmParameter(['imei', 'sn']);
            $validateResult = $this->validate($data, [
                'imei|设备IMEI' => 'min:2',
                'sn|设备SN' => 'min:2'
            ]);
            if (true !== $validateResult) {
                return $this->jmReturnJson(4001, $validateResult);
            }

            $this->jmUnsetEmpty($data);

            if (empty($data['imei']) && empty($data['sn'])) {
                return $this->jmReturnJson(4002, 'IMEI 和 SN 至少一个');
            }

            /*
            SELECT u.username,u.password,u.password2,s.sn,d.imei FROM yx_user AS u
            LEFT JOIN yx_device AS d ON d.user_id=u.id
            LEFT JOIN yx_sn AS s ON s.id=d.`sn_id`
            WHERE u.deleted_at IS NULL AND d.`deleted_at` IS NULL AND s.`deleted_at` IS NULL AND d.imei='12345678901'

            SELECT u.username,u.password,u.password2,s.sn,d.imei FROM yx_user AS u
            LEFT JOIN yx_device AS d ON d.user_id=u.id
            LEFT JOIN yx_sn AS s ON s.id=d.`sn_id`
            WHERE u.deleted_at IS NULL AND d.`deleted_at` IS NULL AND s.`deleted_at` IS NULL AND s.sn='PZMF7DLNV4AAJZM7'
             */

            $query = \think\Db::name('user')->alias('u')->field(['u.username', 'u.password2'=>'password', 's.sn', 'd.imei'])
                    ->join('device d', 'd.user_id=u.id', 'left')
                    ->join('sn s', 's.id=d.sn_id', 'left')
                    ->whereNull('u.deleted_at')
                    ->whereNull('d.deleted_at')
                    ->whereNull('s.deleted_at');

            if (isset($data['imei'])) {
                $condition = ['d.imei' => $data['imei']];
            } else if (isset($data['sn'])) {
                $condition = ['s.sn' => $data['sn']];
            }

            $user = $query->where($condition)->find();
            
            if (is_null($user)) {
                return $this->jmReturnJson(4002, '关联用户不存在');
            }

            $user['password'] = substr($user['password'], 3, -3);
            $user['cloud'] = \think\Config::get('clouddisk.domain') . 'remote.php/webdav/';

            return $this->jmReturnJson(200, '获取用户数据成功', $user);
        } catch (\Exception $e) {
            return $this->jmException($e, false);
        }
    }
}